#ifndef __MBDEF_H
#define __MBDEF_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "stdint.h"
#include "dat_quene.h"

#ifndef MB_MUL_TASK_EN
#define MB_MUL_TASK_EN 1
#endif

#ifndef MB_TCP_IP_EN
#define MB_TCP_IP_EN 1
#endif

#define MB_BUFF_SIZE (256)
#define MMB_TIMEOUT_DEFAULT_MS (120)

#define MB_EVENT_RCV_END (0x01)	  
#define MB_EVENT_MMB_READY (0x02) 
#define MB_EVENT_TIMEOUT (0x04)	  
#define MB_EVENT_SEND_END (0x08)  
#define MB_EVENT_NEW_CMD (0x10)	  

#define MB_FUN_READ_COILS_ENABLED (1)			
#define MB_FUN_READ_DISCRETE_INPUTS_ENABLED (1) 
#define MB_FUN_READ_REG_ENABLED (1)				
#define MB_FUN_READ_INPUT_ENABLED (1)			
#define MB_FUN_WRITE_COIL_ENABLED (1)			
#define MB_FUN_WRITE_REG_ENABLED (1)			
#define MB_FUN_WRITE_MULTIPLE_COILS_ENABLED (1) 
#define MB_FUN_WRITE_MULTIPLE_REG_ENABLED (1)	
#define MB_FUN_W_R_MULTIPLE_REG_ENABLED (1)		

#define MB_REG_COILS_CB_ENABLE (MB_FUN_READ_COILS_ENABLED + MB_FUN_WRITE_COIL_ENABLED + MB_FUN_WRITE_MULTIPLE_COILS_ENABLED)
#define MB_REG_HOLDING_CB_ENABLE (MB_FUN_READ_REG_ENABLED + MB_FUN_WRITE_REG_ENABLED + MB_FUN_WRITE_MULTIPLE_REG_ENABLED + MB_FUN_W_R_MULTIPLE_REG_ENABLED)
#define MB_REG_INPUT_CB_ENABLE (MB_FUN_READ_INPUT_ENABLED)
#define MB_REG_DISCRETE_CB_ENABLE (MB_FUN_READ_DISCRETE_INPUTS_ENABLED)

#define MB_COIL_ON 0xFF00
#define MB_COIL_OFF 0x0000

#define MB_ERR_CODE_MSK 0x80

#define MB_ERR_NONE 0		   
#define MB_ERR_FUN_CODE 1	   
#define MB_ERR_NOREG 2		   
#define MB_ERR_DATA 3		   
#define MB_ERR_DEVICE_FAULT 4  
#define MB_ERR_CONFIRM 5	   
#define MB_ERR_BUSY 7		   
#define MB_ERR_PARITY 8		   
#define MB_ERR_NET_PATH 10	   
#define MB_ERR_NET_LOST 11	   
#define MB_ERR_HAL_PARITY 0x40 

#define MB_ERR_RET_ID 122	
#define MB_ERR_RET_CODE 123 
#define MB_ERR_CRC_LRC 124
#define MB_ERR_HAL 125
#define MB_ETIMEDOUT 126
#define MB_ERR_UNKNOWN 127

#define MB_NULL (0)

#define MB_DAT_TYP_DEF
	typedef unsigned char mb_slave_id_type;
	typedef unsigned short mb_reg_num_type;
	typedef unsigned short mb_reg_addr_type;
	typedef unsigned short mb_reg_data_type;

	typedef union
	{
		uint16_t Val;
		uint16_t uVal;
		int16_t iVal;
		uint16_t uval;
		int16_t ival;
		struct
		{
#ifndef BIG_ENDIAN
			uint8_t LB;
			uint8_t HB;
#else
		uint8_t HB;
		uint8_t LB;
#endif
		} byte;
	} mb_data_type;

#define MB_FUN_CODE_LIST

	typedef enum
	{
		FUN_CODE_NONE = 0,
		FUN_CODE_READ_COILS = 0x01,
		FUN_CODE_READ_DISCRETE = 0x02,
		FUN_CODE_READ_REG = 0x03,
		FUN_CODE_READ_INPUT = 0x04,
		FUN_CODE_WRITE_COIL = 0x05,
		FUN_CODE_WRITE_REG = 0x06,
		FUN_CODE_WRITE_MULTIPLE_COIL = 0x0F,
		FUN_CODE_WRITE_MULTIPLE_REG = 0x10,
		FUN_CODE_WRITE_MASK = 0x16,
		FUN_CODE_W_R_MULTIPLE_REG = 0x17,
		FUN_CODE_READ_SLAVE_ID = 0x2B,
		FUN_GUS_REG_WRITE = 0x80, 
		FUN_GUS_REG_READ = 0x81,
		FUN_GUS_PV_WRITE = 0x82,
		FUN_GUS_PV_READ = 0x83,
		FUN_GUS_LINE_WRITE = 0x84,
		FUN_GUS_AUTO = 0xEE, 
	} mb_cmd_type;

	typedef enum
	{
		MB_RX_IDLE,		  
		MB_RX_RCV,		  
		MB_RX_RCVEND,	  
		MMB_RX_WAIT,	  
		MMB_RX_NACK_WAIT, 
		MMB_RX_NACK_END,  
		MB_RX_TIMEOUT,	  
	} mb_rcv_st_type;

	typedef enum
	{
		MB_TX_IDLE, 
		MB_TX_XMIT	
	} mb_snd_st_type;

	typedef enum
	{
		MB_PAR_NONE,	
		MB_PAR_ODD,		
		MB_PAR_EVEN,	
		MB_PAR_NONE_1S, 
	} mb_parity_type;

	typedef enum
	{
		MB_REG_READ,
		MB_REG_WRITE,
	} mb_reg_mode_type;

	typedef enum
	{
		MB_RTU_MASTER,	   
		MB_RTU_SLAVE,	   
		MB_ASCII_MASTER,   
		MB_ASCII_SLAVE,	   
		MB_TCP_MASTER,	   
		MB_TCP_SLAVE,	   
		MB_TCP_RTU_MASTER, 
		MB_TCP_RTU_SLAVE,  
	} mb_mode_type;

	typedef enum
	{
		MB_BAUD_1200 = 0,
		MB_BAUD_2400 = 1,
		MB_BAUD_4800 = 2,
		MB_BAUD_9600 = 3,
		MB_BAUD_19200 = 4,
		MB_BAUD_38400 = 5,
		MB_BAUD_115200 = 6
	} mb_baud_type;

#define mb_baud_tab_create const uint32_t mb_baud_tab[] = {1200, 2400, 4800, 9600, 19200, 38400, 115200}

	extern const uint32_t mb_baud_tab[];

	typedef union
	{
		uint32_t st;

		struct
		{
			uint8_t master_mode : 1;
			uint8_t rtu_mode : 1;
			uint8_t tcp_mode : 1;
			uint8_t port_st;
			uint8_t connect;
		} bits;
	} mb_run_st_type;

	typedef union
	{
		uint32_t st;

		struct
		{
			uint8_t hal;
			uint8_t id0_rcv; 
		} bits;
	} mb_err_st_type;

	typedef struct
	{
		uint16_t head_num;	 
		uint16_t mb_tcp_num; 
		uint16_t len;		 
		uint8_t sid;		 
	} mb_tcp_mbap_type;

	typedef struct
	{
		void *dat;											 
		mb_cmd_type cmd;									 
		uint8_t device_id;									 
		uint16_t dat_addr;									 
		uint16_t amount;									 
		void (*call_back)(uint8_t cmd_site, uint8_t err_st); 
	} mb_cmd_buff_type;

	typedef struct
	{
		uint8_t (*reg_input_cb)(uint8_t *buff, uint16_t addr, uint16_t reg_len);
		uint8_t (*reg_hold_cb)(uint8_t *buff, uint16_t addr, uint16_t reg_len, mb_reg_mode_type rw_mode);
		uint8_t (*reg_discrete_cb)(uint8_t *buff, uint16_t addr, uint16_t coils_len);
		uint8_t (*reg_coils_cb)(uint8_t *buff, uint16_t addr, uint16_t coils_len, mb_reg_mode_type rw_mode);
	} smb_fun_type;

	typedef struct
	{
		com_quene_type dcmd_quene;	
		uint8_t err_cnt;			
		uint8_t err_sv;				
		uint8_t cmd_amount;			
		uint8_t cmd_exe_index;		
		uint8_t scmd_amount;		
		uint8_t scmd_exe_index;		
		uint8_t st_cmd_empty;		
		mb_cmd_buff_type *pcmdBuff; 
#if MB_MUL_TASK_EN > 0
		void (*mutex_pend)(void);
		void (*mutex_post)(void);
#endif
	} mmb_fun_type;

	typedef struct
	{
		void (*obj_init)(void);
		void (*mb_poll)(void);
		uint8_t (*os_stc_cmd_req)(uint8_t cmd_site, mb_cmd_buff_type *pcmd);
		uint8_t (*os_dyna_cmd_req)(mb_cmd_buff_type *pcmd);
		uint8_t (*os_stc_cmd_del)(uint8_t cmd_site);
		uint8_t (*stc_cmd_req)(uint8_t cmd_site, mb_cmd_buff_type *pcmd);
		uint8_t (*dyna_cmd_req)(mb_cmd_buff_type *pcmd);
		uint8_t (*stc_cmd_del)(uint8_t cmd_site);
		uint8_t (*cmd_ready_num)(void);
		uint8_t (*cmd_idle_num)(void);
		void (*cmd_clr)(void);
	} mb_fun_interface_type;

	typedef struct
	{
		mb_run_st_type run_st;						 
		mb_err_st_type err_st;						 
		mb_rcv_st_type rcv_st;						 
		mb_snd_st_type snd_st;						 
		uint8_t ascii_st;							 
		uint8_t rtu_timer_cnt;						 
		uint8_t b_rtu_timer_on;						 
		uint8_t rtu_timer_sv;						 
		uint8_t st_rcv_end_notice;					 
		uint8_t rtu_master_delay_set;				 
		uint8_t id0_ack_en;							 
		uint8_t rtu_len_cut;						 
		uint8_t slave_id;							 
		uint16_t os_event_base;						 
		uint16_t timeout_set;						 
		uint16_t timeout_cnt;						 
		uint16_t rcv_cnt;							 
		uint16_t snd_size;							 
		uint16_t snd_cnt;							 
		uint16_t success_keep_cnt;					 
		uint16_t fail_keep_cnt;						 
		uint16_t success_cnt;						 
		uint16_t fail_cnt;							 
		uint16_t active_keep_cnt;					 
		uint16_t active_keep_max;					 
		uint16_t idle_time_cnt;						 
		uint16_t sucess_none_time_cnt;				 
		void (*adu_send)(void);						 
		void (*os_event_send)(uint16_t event);		 
		void (*rcv_end_handle_comp)(uint8_t err_st); 
		smb_fun_type slave;							 
		mmb_fun_type master;						 
		mb_cmd_buff_type mcmd_now[2];				 
#if MB_TCP_IP_EN > 0								 
		uint16_t eth_mmb_head;						 
		mb_tcp_mbap_type eth_snd_mbap;				 
		mb_tcp_mbap_type eth_rcv_mbap;				 
		uint8_t (*eth_connect)(void);				 
		uint8_t *adu_buff;							 
		uint8_t dat_buff[MB_BUFF_SIZE + 8];			 
#else
	uint8_t adu_buff[MB_BUFF_SIZE]; 
#endif									  
		const mb_fun_interface_type *api; 
	} mb_obj_type;

	typedef struct
	{
		uint8_t check_val_old;
		uint8_t release_time;
		uint8_t press_time;
		uint8_t opt_out;
	} mb_gus_keep_key_t;

#ifdef __cplusplus
}
#endif

#endif 
